home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / CIRC3.PAK / CIRC3CTL.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  12KB  |  474 lines

  1. // circ3ctl.cpp : Implementation of the CCirc3Ctrl OLE control class.
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1995 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "circ3.h"
  15. #include "circ3ctl.h"
  16. #include "circ3ppg.h"
  17.  
  18.  
  19. #ifdef _DEBUG
  20. #undef THIS_FILE
  21. static char BASED_CODE THIS_FILE[] = __FILE__;
  22. #endif
  23.  
  24.  
  25. IMPLEMENT_DYNCREATE(CCirc3Ctrl, COleControl)
  26.  
  27.  
  28. /////////////////////////////////////////////////////////////////////////////
  29. // Message map
  30.  
  31. BEGIN_MESSAGE_MAP(CCirc3Ctrl, COleControl)
  32.     //{{AFX_MSG_MAP(CCirc3Ctrl)
  33.     ON_WM_LBUTTONDOWN()
  34.     ON_WM_LBUTTONDBLCLK()
  35.     ON_WM_LBUTTONUP()
  36.     ON_WM_SIZE()
  37.     //}}AFX_MSG_MAP
  38.     ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
  39. END_MESSAGE_MAP()
  40.  
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // Dispatch map
  44.  
  45. BEGIN_DISPATCH_MAP(CCirc3Ctrl, COleControl)
  46.     //{{AFX_DISPATCH_MAP(CCirc3Ctrl)
  47.     DISP_PROPERTY(CCirc3Ctrl, "FlashColor", m_flashColor, VT_COLOR)
  48.     DISP_PROPERTY_NOTIFY(CCirc3Ctrl, "CircleShape", m_circleShape, OnCircleShapeChanged, VT_BOOL)
  49.     DISP_PROPERTY_EX(CCirc3Ctrl, "CircleOffset", GetCircleOffset, SetCircleOffset, VT_I2)
  50.     DISP_PROPERTY_EX(CCirc3Ctrl, "Note", GetNote, SetNote, VT_BSTR)
  51.     DISP_STOCKPROP_BACKCOLOR()
  52.     DISP_STOCKPROP_CAPTION()
  53.     DISP_STOCKPROP_FONT()
  54.     DISP_STOCKPROP_FORECOLOR()
  55.     //}}AFX_DISPATCH_MAP
  56.     DISP_FUNCTION_ID(CCirc3Ctrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
  57. END_DISPATCH_MAP()
  58.  
  59.  
  60. /////////////////////////////////////////////////////////////////////////////
  61. // Event map
  62.  
  63. BEGIN_EVENT_MAP(CCirc3Ctrl, COleControl)
  64.     //{{AFX_EVENT_MAP(CCirc3Ctrl)
  65.     EVENT_CUSTOM("ClickIn", FireClickIn, VTS_XPOS_PIXELS  VTS_YPOS_PIXELS)
  66.     EVENT_CUSTOM("ClickOut", FireClickOut, VTS_NONE)
  67.     //}}AFX_EVENT_MAP
  68. END_EVENT_MAP()
  69.  
  70.  
  71. /////////////////////////////////////////////////////////////////////////////
  72. // Property pages
  73.  
  74. // TODO: Add more property pages as needed.  Remember to increase the count!
  75. BEGIN_PROPPAGEIDS(CCirc3Ctrl, 3)
  76.     PROPPAGEID(CCirc3PropPage::guid)
  77.     PROPPAGEID(CLSID_CColorPropPage)
  78.     PROPPAGEID(CLSID_CFontPropPage)
  79. END_PROPPAGEIDS(CCirc3Ctrl)
  80.  
  81.  
  82. /////////////////////////////////////////////////////////////////////////////
  83. // Initialize class factory and guid
  84.  
  85. IMPLEMENT_OLECREATE_EX(CCirc3Ctrl, "CIRC3.Circ3Ctrl.1",
  86.     0x9dbafccf, 0x592f, 0x101b, 0x85, 0xce, 0x0, 0x60, 0x8c, 0xec, 0x29, 0x7b)
  87.  
  88.  
  89. /////////////////////////////////////////////////////////////////////////////
  90. // Type library ID and version
  91.  
  92. IMPLEMENT_OLETYPELIB(CCirc3Ctrl, _tlid, _wVerMajor, _wVerMinor)
  93.  
  94.  
  95. /////////////////////////////////////////////////////////////////////////////
  96. // Interface IDs
  97.  
  98. const IID BASED_CODE IID_DCirc3 =
  99.         { 0x9dbafcd0, 0x592f, 0x101b, { 0x85, 0xce, 0x0, 0x60, 0x8c, 0xec, 0x29, 0x7b } };
  100. const IID BASED_CODE IID_DCirc3Events =
  101.         { 0x9dbafcd1, 0x592f, 0x101b, { 0x85, 0xce, 0x0, 0x60, 0x8c, 0xec, 0x29, 0x7b } };
  102.  
  103.  
  104. /////////////////////////////////////////////////////////////////////////////
  105. // Control type information
  106.  
  107. static const DWORD BASED_CODE _dwCirc3OleMisc =
  108.     OLEMISC_ACTIVATEWHENVISIBLE |
  109.     OLEMISC_SETCLIENTSITEFIRST |
  110.     OLEMISC_INSIDEOUT |
  111.     OLEMISC_CANTLINKINSIDE |
  112.     OLEMISC_RECOMPOSEONRESIZE;
  113.  
  114. IMPLEMENT_OLECTLTYPE(CCirc3Ctrl, IDS_CIRC3, _dwCirc3OleMisc)
  115.  
  116.  
  117. /////////////////////////////////////////////////////////////////////////////
  118. // CCirc3Ctrl::CCirc3CtrlFactory::UpdateRegistry -
  119. // Adds or removes system registry entries for CCirc3Ctrl
  120.  
  121. BOOL CCirc3Ctrl::CCirc3CtrlFactory::UpdateRegistry(BOOL bRegister)
  122. {
  123.     if (bRegister)
  124.         return AfxOleRegisterControlClass(
  125.             AfxGetInstanceHandle(),
  126.             m_clsid,
  127.             m_lpszProgID,
  128.             IDS_CIRC3,
  129.             IDB_CIRC3,
  130.             FALSE,                      //  Not insertable
  131.             _dwCirc3OleMisc,
  132.             _tlid,
  133.             _wVerMajor,
  134.             _wVerMinor);
  135.     else
  136.         return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
  137. }
  138.  
  139.  
  140. /////////////////////////////////////////////////////////////////////////////
  141. // CCirc3Ctrl::CCirc3Ctrl - Constructor
  142.  
  143. CCirc3Ctrl::CCirc3Ctrl()
  144. {
  145.     InitializeIIDs(&IID_DCirc3, &IID_DCirc3Events);
  146.  
  147.     // TODO: Initialize your control's instance data here.
  148. }
  149.  
  150.  
  151. /////////////////////////////////////////////////////////////////////////////
  152. // CCirc3Ctrl::~CCirc3Ctrl - Destructor
  153.  
  154. CCirc3Ctrl::~CCirc3Ctrl()
  155. {
  156.     // TODO: Cleanup your control's instance data here.
  157. }
  158.  
  159.  
  160. /////////////////////////////////////////////////////////////////////////////
  161. // CCirc3Ctrl::OnDraw - Drawing function
  162.  
  163. void CCirc3Ctrl::OnDraw(
  164.             CDC* pdc, const CRect& rcBounds, const CRect&)
  165. {
  166.     CBrush* pOldBrush;
  167.     CBrush bkBrush(TranslateColor(GetBackColor()));
  168.     CPen* pOldPen;
  169.     CRect rc = rcBounds;
  170.     CFont* pOldFont;
  171.     TEXTMETRIC tm;
  172.     const CString& strCaption = InternalGetText();
  173.  
  174.     // Set the ForeColor property color and transparent background mode into the device context
  175.     pdc->SetTextColor(TranslateColor(GetForeColor()));
  176.     pdc->SetBkMode(TRANSPARENT);
  177.  
  178.     // Paint the background using the BackColor property
  179.     pdc->FillRect(rcBounds, &bkBrush);
  180.  
  181.     // Draw the ellipse using the BackColor property and a black pen
  182.     GetDrawRect(&rc);
  183.     pOldBrush = pdc->SelectObject(&bkBrush);
  184.     pOldPen = (CPen*)pdc->SelectStockObject(BLACK_PEN);
  185.     pdc->Ellipse(rc);
  186.  
  187.     // Draw the caption and note using the stock Font and ForeColor properties
  188.     pOldFont = SelectStockFont(pdc);
  189.     GetStockTextMetrics(&tm);
  190.  
  191.     pdc->SetTextAlign(TA_CENTER | TA_TOP);
  192.     pdc->ExtTextOut((rc.left + rc.right) / 2, (rc.top + rc.bottom - tm.tmHeight) / 2,
  193.         ETO_CLIPPED, rc, strCaption, strCaption.GetLength(), NULL);
  194.     pdc->SetTextAlign(TA_LEFT | TA_TOP);
  195.     pdc->ExtTextOut(rcBounds.left, rcBounds.top,
  196.         ETO_CLIPPED, rcBounds, m_note, m_note.GetLength(), NULL);
  197.     pdc->SelectObject(pOldFont);
  198.  
  199.     pdc->SelectObject(pOldPen);
  200.     pdc->SelectObject(pOldBrush);
  201. }
  202.  
  203.  
  204. /////////////////////////////////////////////////////////////////////////////
  205. // CCirc3Ctrl::DoPropExchange - Persistence support
  206.  
  207. void CCirc3Ctrl::DoPropExchange(CPropExchange* pPX)
  208. {
  209.     ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
  210.     COleControl::DoPropExchange(pPX);
  211.  
  212.     if (pPX->GetVersion() == (DWORD)MAKELONG(_wVerMinor, _wVerMajor))
  213.     {
  214.         PX_Bool(pPX, _T("CircleShape"), m_circleShape, TRUE);
  215.         PX_Short(pPX, _T("CircleOffset"), m_circleOffset, 0);
  216.         PX_Long(pPX, _T("FlashColor"), (long &)m_flashColor, RGB(0xFF, 0x00, 0x00));
  217.         PX_String(pPX, _T("Note"), m_note, _T(""));
  218.     }
  219.     else if (pPX->IsLoading())
  220.     {
  221.         // Skip over persistent data
  222.         BOOL bDummy;
  223.         short sDummy;
  224.         long lDummy;
  225.         CString strDummy;
  226.         PX_Bool(pPX, _T("CircleShape"), bDummy, FALSE);
  227.         PX_Short(pPX, _T("CircleOffset"), sDummy, 0);
  228.         PX_Long(pPX, _T("FlashColor"), lDummy, 0);
  229.         PX_String(pPX, _T("Note"), strDummy, _T(""));
  230.  
  231.         // Force property values to these defaults
  232.         m_circleShape = TRUE;
  233.         m_circleOffset = 0;
  234.         m_flashColor = RGB(0xFF, 0x00, 0x00);
  235.         m_note = _T("");
  236.     }
  237. }
  238.  
  239.  
  240. /////////////////////////////////////////////////////////////////////////////
  241. // CCirc3Ctrl::OnResetState - Reset control to default state
  242.  
  243. void CCirc3Ctrl::OnResetState()
  244. {
  245.     COleControl::OnResetState();  // Resets defaults found in DoPropExchange
  246.  
  247.     // TODO: Reset any other control state here.
  248. }
  249.  
  250.  
  251. /////////////////////////////////////////////////////////////////////////////
  252. // CCirc3Ctrl::AboutBox - Display an "About" box to the user
  253.  
  254. void CCirc3Ctrl::AboutBox()
  255. {
  256.     CDialog dlgAbout(IDD_ABOUTBOX_CIRC3);
  257.     dlgAbout.DoModal();
  258. }
  259.  
  260.  
  261. /////////////////////////////////////////////////////////////////////////////
  262. // CCirc3Ctrl message handlers
  263.  
  264.  
  265. void CCirc3Ctrl::OnCircleShapeChanged()
  266. {
  267.     SetModifiedFlag();
  268.  
  269.     // force the control to redraw itself
  270.     InvalidateControl();
  271.  
  272.     // reset the circle offset, if necessary
  273.     if (m_circleShape)
  274.         SetCircleOffset(0);
  275. }
  276.  
  277.  
  278. void CCirc3Ctrl::GetDrawRect(CRect* rc)
  279. {
  280.     if (m_circleShape)
  281.     {
  282.         int cx = rc->right - rc->left;
  283.         int cy = rc->bottom - rc->top;
  284.  
  285.         if (cx > cy)
  286.         {
  287.             rc->left += (cx - cy) / 2;
  288.             rc->right = rc->left + cy;
  289.  
  290.             // offset circle in bounding rect
  291.             rc->left += m_circleOffset;
  292.             rc->right += m_circleOffset;
  293.         }
  294.         else
  295.         {
  296.             rc->top += (cy - cx) / 2;
  297.             rc->bottom = rc->top + cx;
  298.  
  299.             // offset circle in bounding rect
  300.             rc->bottom -= m_circleOffset;
  301.             rc->top -= m_circleOffset;
  302.         }
  303.     }
  304. }
  305.  
  306.  
  307. short CCirc3Ctrl::GetCircleOffset()
  308. {
  309.     return m_circleOffset;
  310. }
  311.  
  312.  
  313. void CCirc3Ctrl::SetCircleOffset(short nNewValue)
  314. {
  315.     // Validate the specified offset value
  316.     if ((m_circleOffset != nNewValue) && m_circleShape && InBounds(nNewValue))
  317.     {
  318.         m_circleOffset = nNewValue;
  319.         SetModifiedFlag();
  320.         InvalidateControl();
  321.     }
  322. }
  323.  
  324.  
  325. BOOL CCirc3Ctrl::InBounds(short nOffset)
  326. {
  327.     int diameter;
  328.     int length;
  329.     int cx;
  330.     int cy;
  331.  
  332.     GetControlSize(&cx, &cy);
  333.  
  334.     if (cx > cy)
  335.     {
  336.         length = cx;
  337.         diameter = cy;
  338.     }
  339.     else
  340.     {
  341.         length = cy;
  342.         diameter = cx;
  343.     }
  344.     if (nOffset < 0)
  345.         nOffset = (short) -nOffset;
  346.     return (diameter / 2 + nOffset) <= (length / 2);
  347. }
  348.  
  349.  
  350. void CCirc3Ctrl::OnLButtonDown(UINT nFlags, CPoint point)
  351. {
  352.     CDC* pdc;
  353.  
  354.     // Flash the color of the control if within the ellipse.
  355.     if (InCircle(point))
  356.     {
  357.         pdc = GetDC();
  358.         FlashColor(pdc);
  359.         ReleaseDC(pdc);
  360.  
  361.         // Fire the ClickIn event
  362.         FireClickIn(point.x, point.y);
  363.     }
  364.     else
  365.         // Fire the ClickOut event
  366.         FireClickOut();
  367.  
  368.     COleControl::OnLButtonDown(nFlags, point);
  369. }
  370.  
  371.  
  372. void CCirc3Ctrl::OnLButtonDblClk(UINT nFlags, CPoint point)
  373. {
  374.     CDC* pdc;
  375.  
  376.     // Flash the color of the control if within the ellipse.
  377.     if (InCircle(point))
  378.     {
  379.         pdc = GetDC();
  380.         FlashColor(pdc);
  381.         ReleaseDC(pdc);
  382.     }
  383.  
  384.     COleControl::OnLButtonDblClk(nFlags, point);
  385. }
  386.  
  387.  
  388. void CCirc3Ctrl::OnLButtonUp(UINT nFlags, CPoint point)
  389. {
  390.     // Redraw the control.
  391.     if (InCircle(point))
  392.         InvalidateControl();
  393.  
  394.     COleControl::OnLButtonUp(nFlags, point);
  395. }
  396.  
  397.  
  398. BOOL CCirc3Ctrl::InCircle(CPoint& point)
  399. {
  400.     CRect rc;
  401.     GetClientRect(rc);
  402.     GetDrawRect(&rc);
  403.  
  404.     // Determine radii
  405.     double a = (rc.right - rc.left) / 2;
  406.     double b = (rc.bottom - rc.top) / 2;
  407.  
  408.     // Determine x, y
  409.     double x = point.x - (rc.left + rc.right) / 2;
  410.     double y = point.y - (rc.top + rc.bottom) / 2;
  411.  
  412.     // Apply ellipse formula
  413.     return ((x * x) / (a * a) + (y * y) / (b * b) <= 1);
  414. }
  415.  
  416.  
  417. void CCirc3Ctrl::FlashColor(CDC* pdc)
  418. {
  419.     CBrush* pOldBrush;
  420.     CBrush flashBrush(TranslateColor(m_flashColor));
  421.     CPen* pOldPen;
  422.     CRect rc;
  423.  
  424.     GetClientRect(rc);
  425.     GetDrawRect(&rc);
  426.     pOldBrush = pdc->SelectObject(&flashBrush);
  427.     pOldPen = (CPen*)pdc->SelectStockObject(BLACK_PEN);
  428.     pdc->Ellipse(rc);
  429.     pdc->SelectObject(pOldPen);
  430.     pdc->SelectObject(pOldBrush);
  431. }
  432.  
  433.  
  434. BOOL CCirc3Ctrl::OnMapPropertyToPage(DISPID dispid, LPCLSID lpclsid,
  435.     BOOL* pbPageOptional)
  436. {
  437.     switch(dispid)
  438.     {
  439.         case dispidFlashColor:
  440.             *lpclsid = CLSID_CColorPropPage;
  441.             *pbPageOptional = TRUE;
  442.             return TRUE;
  443.     }
  444.     return COleControl::OnMapPropertyToPage(dispid, lpclsid, pbPageOptional);
  445. }
  446.  
  447.  
  448. BSTR CCirc3Ctrl::GetNote()
  449. {
  450.     return m_note.AllocSysString();
  451. }
  452.  
  453.  
  454. void CCirc3Ctrl::SetNote(LPCTSTR lpszNewValue)
  455. {
  456.     if (m_note != lpszNewValue)
  457.     {
  458.         m_note = lpszNewValue;
  459.         SetModifiedFlag();
  460.         InvalidateControl();
  461.         BoundPropertyChanged(dispidNote);
  462.     }
  463. }
  464.  
  465. void CCirc3Ctrl::OnSize(UINT nType, int cx, int cy) 
  466. {
  467.     COleControl::OnSize(nType, cx, cy);
  468.     
  469.     // If circle shape is true & cicrle does not fit in new size, reset the offset
  470.     if (m_circleShape && !InBounds(GetCircleOffset()))
  471.         SetCircleOffset(0);
  472.     
  473. }
  474.